home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / span.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  25.1 KB  |  908 lines

  1. /* $Id: span.c,v 1.7 1997/02/09 19:53:43 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: span.c,v $
  26.  * Revision 1.7  1997/02/09 19:53:43  brianp
  27.  * now use TEXTURE_xD enable constants
  28.  *
  29.  * Revision 1.6  1997/02/09 18:43:34  brianp
  30.  * added GL_EXT_texture3D support
  31.  *
  32.  * Revision 1.5  1997/01/28 22:17:44  brianp
  33.  * new RGBA mode logic op support
  34.  *
  35.  * Revision 1.4  1996/09/25 03:22:05  brianp
  36.  * added NO_DRAW_BIT support
  37.  *
  38.  * Revision 1.3  1996/09/15 14:18:55  brianp
  39.  * now use GLframebuffer and GLvisual
  40.  *
  41.  * Revision 1.2  1996/09/15 01:48:58  brianp
  42.  * removed #define NULL 0
  43.  *
  44.  * Revision 1.1  1996/09/13 01:38:16  brianp
  45.  * Initial revision
  46.  *
  47.  */
  48.  
  49.  
  50. /*
  51.  * pixel span rasterization:
  52.  * These functions simulate the rasterization pipeline.
  53.  */
  54.  
  55.  
  56. #include <string.h>
  57. #include "alpha.h"
  58. #include "alphabuf.h"
  59. #include "blend.h"
  60. #include "depth.h"
  61. #include "fog.h"
  62. #include "logic.h"
  63. #include "macros.h"
  64. #include "masking.h"
  65. #include "scissor.h"
  66. #include "span.h"
  67. #include "stencil.h"
  68. #include "texture.h"
  69. #include "types.h"
  70.  
  71.  
  72.  
  73.  
  74. /*
  75.  * Apply the current polygon stipple pattern to a span of pixels.
  76.  */
  77. static void stipple_polygon_span( GLcontext *ctx,
  78.                                   GLuint n, GLint x, GLint y, GLubyte mask[] )
  79. {
  80.    register GLuint i, m, stipple, highbit=0x80000000;
  81.  
  82.    stipple = ctx->PolygonStipple[y % 32];
  83.    m = highbit >> (GLuint) (x % 32);
  84.  
  85.    for (i=0;i<n;i++) {
  86.       if ((m & stipple)==0) {
  87.      mask[i] = 0;
  88.       }
  89.       m = m >> 1;
  90.       if (m==0) {
  91.      m = 0x80000000;
  92.       }
  93.    }
  94. }
  95.  
  96.  
  97.  
  98. /*
  99.  * Clip a pixel span to the current buffer/window boundaries.
  100.  * Return:  0 = all pixels clipped
  101.  *          1 = at least one pixel is visible
  102.  */
  103. static GLuint clip_span( GLcontext *ctx,
  104.                          GLint n, GLint x, GLint y, GLubyte mask[] )
  105. {
  106.    GLint i;
  107.  
  108.    /* Clip to top and bottom */
  109.    if (y<0 || y>=ctx->Buffer->Height) {
  110.       return 0;
  111.    }
  112.  
  113.    /* Clip to left and right */
  114.    if (x>=0 && x+n<=ctx->Buffer->Width) {
  115.       /* no clipping needed */
  116.       return 1;
  117.    }
  118.    else if (x+n<=0) {
  119.       /* completely off left side */
  120.       return 0;
  121.    }
  122.    else if (x>=ctx->Buffer->Width) {
  123.       /* completely off right side */
  124.       return 0;
  125.    }
  126.    else {
  127.       /* clip-test each pixel, this could be done better */
  128.       for (i=0;i<n;i++) {
  129.          if (x+i<0 || x+i>=ctx->Buffer->Width) {
  130.             mask[i] = 0;
  131.          }
  132.       }
  133.       return 1;
  134.    }
  135. }
  136.  
  137.  
  138.  
  139. /*
  140.  * Write a horizontal span of color index pixels to the frame buffer.
  141.  * Stenciling, Depth-testing, etc. are done as needed.
  142.  * Input:  n - number of pixels in the span
  143.  *         x, y - location of leftmost pixel in the span
  144.  *         z - array of [n] z-values
  145.  *         index - array of [n] color indexes
  146.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
  147.  */
  148. void gl_write_index_span( GLcontext *ctx,
  149.                           GLuint n, GLint x, GLint y, GLdepth z[],
  150.               GLuint index[], GLenum primitive )
  151. {
  152.    GLuint i;
  153.    GLubyte mask[MAX_WIDTH];
  154.    GLuint index_save[MAX_WIDTH];
  155.  
  156.    /* init mask to 1's (all pixels are to be written) */
  157.    for (i=0;i<n;i++)
  158.       mask[i] = 1;
  159.  
  160.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  161.       if (clip_span(ctx,n,x,y,mask)==0) {
  162.      return;
  163.       }
  164.    }
  165.  
  166.    /* Per-pixel fog */
  167.    if (ctx->Fog.Enabled
  168.        && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  169.       gl_fog_index_pixels( ctx, n, z, index );
  170.    }
  171.  
  172.    /* Do the scissor test */
  173.    if (ctx->Scissor.Enabled) {
  174.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  175.      return;
  176.       }
  177.    }
  178.  
  179.    /* Polygon Stippling */
  180.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  181.       stipple_polygon_span( ctx, n, x, y, mask );
  182.    }
  183.  
  184.    if (ctx->Stencil.Enabled) {
  185.       /* first stencil test */
  186.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  187.      return;
  188.       }
  189.       /* depth buffering w/ stencil */
  190.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  191.    }
  192.    else if (ctx->Depth.Test) {
  193.       /* regular depth testing */
  194.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  195.    }
  196.  
  197.    if (ctx->RasterMask & NO_DRAW_BIT) {
  198.       /* write no pixels */
  199.       return;
  200.    }
  201.  
  202.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  203.       /* Save a copy of the indexes since LogicOp and IndexMask
  204.        * may change them
  205.        */
  206.       MEMCPY( index_save, index, n * sizeof(GLuint) );
  207.    }
  208.  
  209.    if (ctx->Color.SWLogicOpEnabled) {
  210.       gl_logicop_ci_span( ctx, n, x, y, index, mask );
  211.    }
  212.    if (ctx->Color.SWmasking) {
  213.       gl_mask_index_span( ctx, n, x, y, index );
  214.    }
  215.  
  216.    /* write pixels */
  217.    (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, index, mask );
  218.  
  219.  
  220.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  221.       /*** Also draw to back buffer ***/
  222.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  223.       MEMCPY( index, index_save, n * sizeof(GLuint) );
  224.       if (ctx->Color.SWLogicOpEnabled) {
  225.          gl_logicop_ci_span( ctx, n, x, y, index, mask );
  226.       }
  227.       if (ctx->Color.SWmasking) {
  228.          gl_mask_index_span( ctx, n, x, y, index );
  229.       }
  230.       (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, index, mask );
  231.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  232.    }
  233. }
  234.  
  235.  
  236.  
  237.  
  238. void gl_write_monoindex_span( GLcontext *ctx,
  239.                               GLuint n, GLint x, GLint y, GLdepth z[],
  240.                   GLuint index, GLenum primitive )
  241. {
  242.    GLuint i;
  243.    GLubyte mask[MAX_WIDTH];
  244.    GLuint index_save[MAX_WIDTH];
  245.  
  246.    /* init mask to 1's (all pixels are to be written) */
  247.    for (i=0;i<n;i++)
  248.       mask[i] = 1;
  249.  
  250.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  251.       if (clip_span( ctx,n,x,y,mask)==0) {
  252.      return;
  253.       }
  254.    }
  255.  
  256.    /* Do the scissor test */
  257.    if (ctx->Scissor.Enabled) {
  258.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  259.      return;
  260.       }
  261.    }
  262.  
  263.    /* Polygon Stippling */
  264.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  265.       stipple_polygon_span( ctx, n, x, y, mask );
  266.    }
  267.  
  268.    if (ctx->Stencil.Enabled) {
  269.       /* first stencil test */
  270.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  271.      return;
  272.       }
  273.       /* depth buffering w/ stencil */
  274.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  275.    }
  276.    else if (ctx->Depth.Test) {
  277.       /* regular depth testing */
  278.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  279.    }
  280.  
  281.    if (ctx->RasterMask & NO_DRAW_BIT) {
  282.       /* write no pixels */
  283.       return;
  284.    }
  285.  
  286.    if ((ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP))
  287.         || ctx->Color.SWLogicOpEnabled || ctx->Color.SWmasking) {
  288.       GLuint ispan[MAX_WIDTH];
  289.       /* index may change, replicate single index into an array */
  290.       for (i=0;i<n;i++) {
  291.      ispan[i] = index;
  292.       }
  293.  
  294.       if (ctx->Fog.Enabled
  295.           && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  296.      gl_fog_index_pixels( ctx, n, z, ispan );
  297.       }
  298.  
  299.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  300.          MEMCPY( index_save, index, n * sizeof(GLuint) );
  301.       }
  302.  
  303.       if (ctx->Color.SWLogicOpEnabled) {
  304.      gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
  305.       }
  306.  
  307.       if (ctx->Color.SWmasking) {
  308.          gl_mask_index_span( ctx, n, x, y, ispan );
  309.       }
  310.  
  311.       (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, ispan, mask );
  312.  
  313.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  314.          /*** Also draw to back buffer ***/
  315.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  316.          for (i=0;i<n;i++) {
  317.             ispan[i] = index;
  318.          }
  319.          if (ctx->Color.SWLogicOpEnabled) {
  320.             gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
  321.          }
  322.          if (ctx->Color.SWmasking) {
  323.             gl_mask_index_span( ctx, n, x, y, ispan );
  324.          }
  325.          (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, ispan, mask );
  326.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  327.       }
  328.    }
  329.    else {
  330.       (*ctx->Driver.WriteMonoindexSpan)( ctx, n, x, y, mask );
  331.  
  332.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  333.          /*** Also draw to back buffer ***/
  334.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  335.          (*ctx->Driver.WriteMonoindexSpan)( ctx, n, x, y, mask );
  336.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  337.       }
  338.    }
  339. }
  340.  
  341.  
  342.  
  343. void gl_write_color_span( GLcontext *ctx,
  344.                           GLuint n, GLint x, GLint y, GLdepth z[],
  345.               GLubyte r[], GLubyte g[],
  346.               GLubyte b[], GLubyte a[],
  347.               GLenum primitive )
  348. {
  349.    GLuint i;
  350.    GLubyte mask[MAX_WIDTH];
  351.    GLboolean write_all = GL_TRUE;
  352.    GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH];
  353.    GLubyte *red, *green, *blue, *alpha;
  354.  
  355.    /* init mask to 1's (all pixels are to be written) */
  356.    for (i=0;i<n;i++)
  357.       mask[i] = 1;
  358.  
  359.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  360.       if (clip_span( ctx,n,x,y,mask)==0) {
  361.      return;
  362.       }
  363.       write_all = GL_FALSE;
  364.    }
  365.  
  366.    if ((primitive==GL_BITMAP && ctx->MutablePixels)
  367.        || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  368.       /* must make a copy of the colors since they may be modified */
  369.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  370.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  371.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  372.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  373.       red = rtmp;
  374.       green = gtmp;
  375.       blue = btmp;
  376.       alpha = atmp;
  377.    }
  378.    else {
  379.       red   = r;
  380.       green = g;
  381.       blue  = b;
  382.       alpha = a;
  383.    }
  384.  
  385.    /* Per-pixel fog */
  386.    if (ctx->Fog.Enabled
  387.        && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  388.       gl_fog_color_pixels( ctx, n, z, red, green, blue, alpha );
  389.    }
  390.  
  391.    /* Do the scissor test */
  392.    if (ctx->Scissor.Enabled) {
  393.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  394.      return;
  395.       }
  396.       write_all = GL_FALSE;
  397.    }
  398.  
  399.    /* Polygon Stippling */
  400.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  401.       stipple_polygon_span( ctx, n, x, y, mask );
  402.       write_all = GL_FALSE;
  403.    }
  404.  
  405.    /* Do the alpha test */
  406.    if (ctx->Color.AlphaEnabled) {
  407.       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
  408.      return;
  409.       }
  410.       write_all = GL_FALSE;
  411.    }
  412.  
  413.    if (ctx->Stencil.Enabled) {
  414.       /* first stencil test */
  415.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  416.      return;
  417.       }
  418.       /* depth buffering w/ stencil */
  419.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  420.       write_all = GL_FALSE;
  421.    }
  422.    else if (ctx->Depth.Test) {
  423.       /* regular depth testing */
  424.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  425.       if (m==0) {
  426.          return;
  427.       }
  428.       if (m<n) {
  429.          write_all = GL_FALSE;
  430.       }
  431.    }
  432.  
  433.    if (ctx->RasterMask & NO_DRAW_BIT) {
  434.       /* write no pixels */
  435.       return;
  436.    }
  437.  
  438.    /* logic op or blending */
  439.    if (ctx->Color.SWLogicOpEnabled) {
  440.       gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  441.    }
  442.    else if (ctx->Color.BlendEnabled) {
  443.       gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  444.    }
  445.  
  446.    /* Color component masking */
  447.    if (ctx->Color.SWmasking) {
  448.       gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  449.    }
  450.  
  451.    /* write pixels */
  452.    (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  453.                                   write_all ? NULL : mask );
  454.    if (ctx->RasterMask & ALPHABUF_BIT) {
  455.       gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  456.    }
  457.  
  458.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  459.       /*** Also render to back buffer ***/
  460.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  461.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  462.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  463.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  464.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  465.       if (ctx->Color.SWLogicOpEnabled) {
  466.          gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  467.       }
  468.       else  if (ctx->Color.BlendEnabled) {
  469.          gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  470.       }
  471.       if (ctx->Color.SWmasking) {
  472.          gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  473.       }
  474.       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  475.                               write_all ? NULL : mask );
  476.       if (ctx->RasterMask & ALPHABUF_BIT) {
  477.          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  478.          gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  479.          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  480.       }
  481.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  482.    }
  483.  
  484. }
  485.  
  486.  
  487.  
  488. /*
  489.  * Write a horizontal span of color pixels to the frame buffer.
  490.  * The color is initially constant for the whole span.
  491.  * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
  492.  * Input:  n - number of pixels in the span
  493.  *         x, y - location of leftmost pixel in the span
  494.  *         z - array of [n] z-values
  495.  *         r, g, b, a - the color of the pixels
  496.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  497.  */
  498. void gl_write_monocolor_span( GLcontext *ctx,
  499.                               GLuint n, GLint x, GLint y, GLdepth z[],
  500.                   GLint r, GLint g, GLint b, GLint a,
  501.                               GLenum primitive )
  502. {
  503.    GLuint i;
  504.    GLubyte mask[MAX_WIDTH];
  505.    GLboolean write_all = GL_TRUE;
  506.    GLubyte red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH];
  507.  
  508.    /* init mask to 1's (all pixels are to be written) */
  509.    for (i=0;i<n;i++)
  510.       mask[i] = 1;
  511.  
  512.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  513.       if (clip_span( ctx,n,x,y,mask)==0) {
  514.      return;
  515.       }
  516.       write_all = GL_FALSE;
  517.    }
  518.  
  519.    /* Do the scissor test */
  520.    if (ctx->Scissor.Enabled) {
  521.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  522.      return;
  523.       }
  524.       write_all = GL_FALSE;
  525.    }
  526.  
  527.    /* Polygon Stippling */
  528.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  529.       stipple_polygon_span( ctx, n, x, y, mask );
  530.       write_all = GL_FALSE;
  531.    }
  532.  
  533.    /* Do the alpha test */
  534.    if (ctx->Color.AlphaEnabled) {
  535.       GLubyte alpha[MAX_WIDTH];
  536.       for (i=0;i<n;i++) {
  537.          alpha[i] = a;
  538.       }
  539.       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
  540.      return;
  541.       }
  542.       write_all = GL_FALSE;
  543.    }
  544.  
  545.    if (ctx->Stencil.Enabled) {
  546.       /* first stencil test */
  547.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  548.      return;
  549.       }
  550.       /* depth buffering w/ stencil */
  551.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  552.       write_all = GL_FALSE;
  553.    }
  554.    else if (ctx->Depth.Test) {
  555.       /* regular depth testing */
  556.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  557.       if (m==0) {
  558.          return;
  559.       }
  560.       if (m<n) {
  561.          write_all = GL_FALSE;
  562.       }
  563.    }
  564.  
  565.    if (ctx->RasterMask & NO_DRAW_BIT) {
  566.       /* write no pixels */
  567.       return;
  568.    }
  569.  
  570.    if (ctx->Color.BlendEnabled || ctx->Color.SWLogicOpEnabled
  571.        || ctx->Color.SWmasking) {
  572.       /* assign same color to each pixel */
  573.       for (i=0;i<n;i++) {
  574.      if (mask[i]) {
  575.         red[i]   = r;
  576.         green[i] = g;
  577.         blue[i]  = b;
  578.         alpha[i] = a;
  579.      }
  580.       }
  581.  
  582.       if (ctx->Color.SWLogicOpEnabled) {
  583.          gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  584.       }
  585.       else if (ctx->Color.BlendEnabled) {
  586.          gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  587.       }
  588.  
  589.       /* Color component masking */
  590.       if (ctx->Color.SWmasking) {
  591.          gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  592.       }
  593.  
  594.       /* write pixels */
  595.       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  596.                                      write_all ? NULL : mask );
  597.       if (ctx->RasterMask & ALPHABUF_BIT) {
  598.          gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  599.       }
  600.  
  601.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  602.          /*** Also draw to back buffer ***/
  603.          for (i=0;i<n;i++) {
  604.             if (mask[i]) {
  605.                red[i]   = r;
  606.                green[i] = g;
  607.                blue[i]  = b;
  608.                alpha[i] = a;
  609.             }
  610.          }
  611.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  612.          if (ctx->Color.SWLogicOpEnabled) {
  613.             gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask);
  614.          }
  615.          else if (ctx->Color.BlendEnabled) {
  616.             gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  617.          }
  618.          if (ctx->Color.SWmasking) {
  619.             gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  620.          }
  621.          (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  622.                                         write_all ? NULL : mask );
  623.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  624.          if (ctx->RasterMask & ALPHABUF_BIT) {
  625.             ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  626.             gl_write_alpha_span( ctx, n, x, y, alpha,
  627.                                  write_all ? NULL : mask );
  628.             ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  629.          }
  630.       }
  631.    }
  632.    else {
  633.       (*ctx->Driver.WriteMonocolorSpan)( ctx, n, x, y, mask );
  634.       if (ctx->RasterMask & ALPHABUF_BIT) {
  635.          gl_write_mono_alpha_span( ctx, n, x, y, a, write_all ? NULL : mask );
  636.       }
  637.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  638.          /* Also draw to back buffer */
  639.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  640.          (*ctx->Driver.WriteMonocolorSpan)( ctx, n, x, y, mask );
  641.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  642.          if (ctx->RasterMask & ALPHABUF_BIT) {
  643.             ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  644.             gl_write_mono_alpha_span( ctx, n, x, y, a,
  645.                                       write_all ? NULL : mask );
  646.             ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  647.          }
  648.       }
  649.    }
  650. }
  651.  
  652.  
  653.  
  654. /*
  655.  * Write a horizontal span of textured pixels to the frame buffer.
  656.  * The color of each pixel is different.
  657.  * Alpha-testing, stenciling, depth-testing, and blending are done
  658.  * as needed.
  659.  * Input:  n - number of pixels in the span
  660.  *         x, y - location of leftmost pixel in the span
  661.  *         z - array of [n] z-values
  662.  *         s, t - array of (s,t) texture coordinates for each pixel
  663.  *         lambda - array of texture lambda values
  664.  *         red, green, blue, alpha - array of [n] color components
  665.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  666.  */
  667. void gl_write_texture_span( GLcontext *ctx,
  668.                             GLuint n, GLint x, GLint y, GLdepth z[],
  669.                 GLfloat s[], GLfloat t[], GLfloat u[],
  670.                             GLfloat lambda[],
  671.                 GLubyte r[], GLubyte g[],
  672.                 GLubyte b[], GLubyte a[],
  673.                 GLenum primitive )
  674. {
  675.    GLuint i;
  676.    GLubyte mask[MAX_WIDTH];
  677.    GLboolean write_all = GL_TRUE;
  678.    GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH];
  679.    GLubyte *red, *green, *blue, *alpha;
  680.  
  681.    /* init mask to 1's (all pixels are to be written) */
  682.    for (i=0;i<n;i++)
  683.       mask[i] = 1;
  684.  
  685.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  686.       if (clip_span( ctx,n,x,y,mask)==0) {
  687.      return;
  688.       }
  689.       write_all = GL_FALSE;
  690.    }
  691.  
  692.  
  693.    if (primitive==GL_BITMAP || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  694.       /* must make a copy of the colors since they may be modified */
  695.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  696.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  697.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  698.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  699.       red = rtmp;
  700.       green = gtmp;
  701.       blue = btmp;
  702.       alpha = atmp;
  703.    }
  704.    else {
  705.       red   = r;
  706.       green = g;
  707.       blue  = b;
  708.       alpha = a;
  709.    }
  710.  
  711.    /* Texture */
  712.    if (ctx->Texture.Enabled & TEXTURE_3D) {
  713.       gl_texture_pixels_3d( ctx, n, s, t, u, lambda, red, green, blue, alpha );
  714.    }
  715.    else if (ctx->Texture.Enabled & TEXTURE_2D) {
  716.       gl_texture_pixels_2d( ctx, n, s, t, lambda, red, green, blue, alpha );
  717.    }
  718.    else if (ctx->Texture.Enabled & TEXTURE_1D) {
  719.       gl_texture_pixels_1d( ctx, n, s, lambda, red, green, blue, alpha );
  720.    }
  721.  
  722.  
  723.    /* Per-pixel fog */
  724.    if (ctx->Fog.Enabled
  725.        && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  726.       gl_fog_color_pixels( ctx, n, z, red, green, blue, alpha );
  727.    }
  728.  
  729.    /* Do the scissor test */
  730.    if (ctx->Scissor.Enabled) {
  731.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  732.      return;
  733.       }
  734.       write_all = GL_FALSE;
  735.    }
  736.  
  737.    /* Polygon Stippling */
  738.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  739.       stipple_polygon_span( ctx, n, x, y, mask );
  740.       write_all = GL_FALSE;
  741.    }
  742.  
  743.    /* Do the alpha test */
  744.    if (ctx->Color.AlphaEnabled) {
  745.       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
  746.      return;
  747.       }
  748.       write_all = GL_FALSE;
  749.    }
  750.  
  751.    if (ctx->Stencil.Enabled) {
  752.       /* first stencil test */
  753.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  754.      return;
  755.       }
  756.       /* depth buffering w/ stencil */
  757.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  758.       write_all = GL_FALSE;
  759.    }
  760.    else if (ctx->Depth.Test) {
  761.       /* regular depth testing */
  762.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  763.       if (m==0) {
  764.          return;
  765.       }
  766.       if (m<n) {
  767.          write_all = GL_FALSE;
  768.       }
  769.    }
  770.  
  771.    if (ctx->RasterMask & NO_DRAW_BIT) {
  772.       /* write no pixels */
  773.       return;
  774.    }
  775.  
  776.    /* blending */
  777.    if (ctx->Color.SWLogicOpEnabled) {
  778.       gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  779.    }
  780.    else  if (ctx->Color.BlendEnabled) {
  781.       gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  782.    }
  783.  
  784.    if (ctx->Color.SWmasking) {
  785.       gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  786.    }
  787.  
  788.    /* write pixels */
  789.    (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  790.                                   write_all ? NULL : mask );
  791.    if (ctx->RasterMask & ALPHABUF_BIT) {
  792.       gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  793.    }
  794.  
  795.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  796.       /* Also draw to back buffer */
  797.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  798.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  799.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  800.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  801.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  802.       if (ctx->Color.SWLogicOpEnabled) {
  803.          gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  804.       }
  805.       else if (ctx->Color.BlendEnabled) {
  806.          gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  807.       }
  808.       if (ctx->Color.SWmasking) {
  809.          gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  810.       }
  811.       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  812.                                      write_all ? NULL : mask );
  813.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  814.       if (ctx->RasterMask & ALPHABUF_BIT) {
  815.          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  816.          gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  817.          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  818.       }
  819.    }
  820. }
  821.  
  822.  
  823.  
  824. /*
  825.  * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
  826.  * reading ouside the buffer's boundaries.
  827.  */
  828. void gl_read_color_span( GLcontext *ctx,
  829.                          GLuint n, GLint x, GLint y,
  830.              GLubyte red[], GLubyte green[],
  831.              GLubyte blue[], GLubyte alpha[] )
  832. {
  833.    register GLuint i;
  834.  
  835.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  836.       /* completely above, below, or right */
  837.       for (i=0;i<n;i++) {
  838.      red[i] = green[i] = blue[i] = alpha[i] = 0;
  839.       }
  840.    }
  841.    else {
  842.       if (x>=0 && x+n<=ctx->Buffer->Width) {
  843.      /* OK */
  844.      (*ctx->Driver.ReadColorSpan)( ctx, n, x, y, red, green, blue, alpha );
  845.          if (ctx->RasterMask & ALPHABUF_BIT) {
  846.             gl_read_alpha_span( ctx, n, x, y, alpha );
  847.          }
  848.       }
  849.       else {
  850.      i = 0;
  851.      if (x<0) {
  852.         while (x<0 && n>0) {
  853.            red[i] = green[i] =  blue[i] = alpha[i] = 0;
  854.            x++;
  855.            n--;
  856.            i++;
  857.         }
  858.      }
  859.      n = MIN2( n, ctx->Buffer->Width - x );
  860.      (*ctx->Driver.ReadColorSpan)( ctx, n, x, y, red+i, green+i, blue+i, alpha+i);
  861.          if (ctx->RasterMask & ALPHABUF_BIT) {
  862.             gl_read_alpha_span( ctx, n, x, y, alpha+i );
  863.          }
  864.       }
  865.    }
  866. }
  867.  
  868.  
  869.  
  870.  
  871. /*
  872.  * Read CI pixels from frame buffer.  Clipping will be done to prevent
  873.  * reading ouside the buffer's boundaries.
  874.  */
  875. void gl_read_index_span( GLcontext *ctx,
  876.                          GLuint n, GLint x, GLint y, GLuint indx[] )
  877. {
  878.    register GLuint i;
  879.  
  880.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  881.       /* completely above, below, or right */
  882.       for (i=0;i<n;i++) {
  883.      indx[i] = 0;
  884.       }
  885.    }
  886.    else {
  887.       if (x>=0 && x+n<=ctx->Buffer->Width) {
  888.      /* OK */
  889.      (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, indx );
  890.       }
  891.       else {
  892.      i = 0;
  893.      if (x<0) {
  894.         while (x<0 && n>0) {
  895.            indx[i] = 0;
  896.            x++;
  897.            n--;
  898.            i++;
  899.         }
  900.      }
  901.      n = MIN2( n, ctx->Buffer->Width - x );
  902.      (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, indx+i );
  903.       }
  904.    }
  905. }
  906.  
  907.  
  908.